package com.shou.domain.park.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shou.domain.common.AbstractService;
import com.shou.domain.common.PageQueryEntity;
import com.shou.domain.park.model.ParkingRecordEntity;
import com.shou.domain.park.repository.IParkingRecordRepository;
import com.shou.domain.park.service.IParkingRecordService;
import com.shou.types.common.ReturnCodeEnum;
import com.shou.types.common.TableNameEnum;
import com.shou.types.exception.SystemException;
import com.shou.types.utils.TimeUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
* @author Nemo
* @description 针对表【parkingrecords(停车记录表，记录车辆的进出信息)】的数据库操作Service实现
* @createDate 2025-02-07 22:10:51
*/
@Service
public class ParkingRecordService extends AbstractService implements IParkingRecordService {
    @Resource
    private IParkingRecordRepository parkingRecordRepository;
    @Override
    public void insertParkingRecord(ParkingRecordEntity parkingRecordEntity) {
        validateParkingRecordEntity(parkingRecordEntity);
        parkingRecordRepository.insert(parkingRecordEntity);
    }

    @Override
    public ParkingRecordEntity getParkingRecordById(Integer id) {
        return parkingRecordRepository.getParkingRecordById(id);
    }

    @Override
    public IPage<ParkingRecordEntity> pageQuery(PageQueryEntity pageQueryEntity) {
        pageQueryEntity.setSortName(camelToSnake(pageQueryEntity.getSortName()));
        validateQueryParams(pageQueryEntity, TableNameEnum.PARKING_RECORD);
        return parkingRecordRepository.getParkingRecordsPage(pageQueryEntity);
    }

    @Override
    public void updateParkingRecordById(ParkingRecordEntity parkingRecordEntity) {
        Integer id = parkingRecordEntity.getId();
        if(id == null || !checkIfExistById(id, TableNameEnum.PARKING_RECORD)){
            throw new RuntimeException("id为" + id + "的记录不存在");
        }
//        validateParkingRecordEntity(parkingRecordEntity, parkingRecordEntity.getId());
        parkingRecordRepository.updateParkingRecordById(parkingRecordEntity);
    }

    @Override
    public List<Long> getInCountsByCodeAndStartTime(String lotCode, List<String> xAxisData, String timeUnit) {
        List<String[]> timeRanges = TimeUtil.getTimeRangesInxAxisData(lotCode, xAxisData, timeUnit);
        List<Future<Long>> futures = new ArrayList<>();
        ThreadPoolExecutor jdbcThreadPoll  = new ThreadPoolExecutor(
                50,
                100,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1000),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for (String[] range : timeRanges) {
            futures.add(jdbcThreadPoll.submit(() -> {
                try {
                    return parkingRecordRepository.getInCountsByTimeRanges(lotCode, range[0], range[1]);
                } catch (Exception e) {
                    throw new SystemException(SystemException.ErrorCodeEnum.JDBC_THREAD_POOL_EXECUTE_FAILED.getMessage(), e.getMessage(), ReturnCodeEnum.RC500);
                }
            }));
        }
        // 关闭线程池，禁止提交任务
        jdbcThreadPoll.shutdown();

        // 收集结果
        List<Long> results = new ArrayList<>();
        for (Future<Long> future : futures) {
            try {
                results.add(future.get()); // 这里会阻塞直到结果可用
            } catch (InterruptedException | ExecutionException e) {
                System.err.println("任务执行中断" + e.getMessage());
            }
        }
        return results;
    }

    @Override
    public List<Long> getOutCountsByCodeAndStartTime(String lotCode, List<String> xAxisData, String timeUnit) {
        List<String[]> timeRanges = TimeUtil.getTimeRangesInxAxisData(lotCode, xAxisData, timeUnit);
        List<Future<Long>> futures = new ArrayList<>();
        ThreadPoolExecutor jdbcThreadPoll  = new ThreadPoolExecutor(
                50,
                100,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1000),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for (String[] range : timeRanges) {
            futures.add(jdbcThreadPoll.submit(() -> {
                try {
                    return parkingRecordRepository.getOutCountsByTimeRanges(lotCode, range[0], range[1]);
                } catch (Exception e) {
                    throw new SystemException(SystemException.ErrorCodeEnum.JDBC_THREAD_POOL_EXECUTE_FAILED.getMessage(), e.getMessage(), ReturnCodeEnum.RC500);
                }
            }));
        }
        jdbcThreadPoll.shutdown();

        List<Long> results = new ArrayList<>();
        for (Future<Long> future : futures) {
            try {
                results.add(future.get()); // 这里会阻塞直到结果可用
            } catch (InterruptedException | ExecutionException e) {
                System.err.println("任务执行中断" + e.getMessage());
            }
        }
        return results;
    }

    @Override
    public List<Double> getOccupancyRatesByCodeAndStartAndEndTime(String lotCode, List<String> xAxisData, String timeUnit, Long totalSpaces) {
        List<String[]> timeRanges = TimeUtil.getTimeRangesInxAxisData(lotCode, xAxisData, timeUnit);
        List<Future<Long>> futures = new ArrayList<>();
        ThreadPoolExecutor jdbcThreadPoll  = new ThreadPoolExecutor(
                50,
                100,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1000),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for (String[] range : timeRanges) {
            futures.add(jdbcThreadPoll.submit(() -> {
                try {
                    return parkingRecordRepository.getOccupancyCount(lotCode, range[0], range[1]);
                } catch (Exception e) {
                    throw new SystemException(SystemException.ErrorCodeEnum.JDBC_THREAD_POOL_EXECUTE_FAILED.getMessage(), e.getMessage(), ReturnCodeEnum.RC500);
                }
            }));
        }
        jdbcThreadPoll.shutdown();

        List<Double> results = new ArrayList<>();
        for (Future<Long> future : futures) {
            try {
                results.add(Math.round(((double) future.get() / totalSpaces) * 10000.0) / 10000.0);
            } catch (InterruptedException | ExecutionException e) {
                System.err.println("任务执行中断" + e.getMessage());
            }
        }
        return results;
    }

    @Override
    public BigDecimal getTotalIncomeByCodeAndStartTime(String lotCode, LocalDateTime startTime, LocalDateTime endTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return parkingRecordRepository.getTotalIncomeByCodeAndStartTime(lotCode, startTime.format(formatter), endTime.format(formatter));
    }

    @Override
    public void deleteByIds(List<Integer> ids) {
        super.deleteByIds(ids, TableNameEnum.PARKING_RECORD);
    }

    @Override
    public void deleteAll() {
        super.deleteAll(TableNameEnum.PARKING_RECORD);
    }

    private void validateParkingRecordEntity(ParkingRecordEntity parkingRecord, Integer... excludeIds) {
//        validateByReservedUserId(parkingRecord.getUserId(), TableNameEnum.PARKING_RECORD.getEnTableName(), excludeIds);
        validateBySpaceCode(parkingRecord.getSpaceCode(), TableNameEnum.PARKING_SPACE.getEnTableName(), excludeIds);
    }
}




